package com.maxverse.boot.web2image.screenshot.service;

import com.microsoft.playwright.*;
import com.microsoft.playwright.options.LoadState;
import com.microsoft.playwright.options.ScreenshotType;
import com.maxverse.boot.web2image.core.exception.Web2ImageException;
import com.maxverse.boot.web2image.common.model.TaskMessage;
import com.maxverse.boot.web2image.screenshot.config.PlaywrightConfig;
import com.maxverse.boot.web2image.screenshot.core.BrowserManager;
import com.microsoft.playwright.options.WaitUntilState;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.nio.file.Path;
import java.util.Arrays;

@Slf4j
@Service
public class ScreenshotExecutor {
    private final BrowserManager browserManager;
    private final PlaywrightConfig config;

    public ScreenshotExecutor(BrowserManager browserManager, PlaywrightConfig config) {
        this.browserManager = browserManager;
        this.config = config;
    }

    public Path takeScreenshot(TaskMessage task, Path outputPath) {
        Browser browser = null;
        try {
            browser = browserManager.acquireBrowser();
            BrowserContext context = createContext(browser, task.getConfig());
            Page page = context.newPage();

            configureViewport(page, task);
            navigateToPage(page, task);
            
            // 截图
            Page.ScreenshotOptions options = createScreenshotOptions(task, outputPath);
            page.screenshot(options);
            
            context.close();
            return outputPath;
        } catch (Exception e) {
            throw new Web2ImageException("Failed to take screenshot: " + e.getMessage(), e);
        } finally {
            if (browser != null) {
                browserManager.releaseBrowser(browser);
            }
        }
    }

    private BrowserContext createContext(Browser browser, TaskMessage.TaskConfigMessage config) {
        Browser.NewContextOptions options = new Browser.NewContextOptions();
        if (config != null) {
            if (config.getUserAgent() != null) {
                options.setUserAgent(config.getUserAgent());
            }
            if (config.getProxy() != null) {
                options.setProxy(config.getProxy());
            }
            if (config.getJsEnabled() != null) {
                options.setJavaScriptEnabled(config.getJsEnabled());
            }
        }
        return browser.newContext(options);
    }

    private void configureViewport(Page page, TaskMessage task) {
        page.setViewportSize(
            task.getWidth() != null ? task.getWidth() : config.getScreenshot().getDefaultWidth(),
            task.getHeight() != null ? task.getHeight() : config.getScreenshot().getDefaultHeight()
        );
    }

    private void navigateToPage(Page page, TaskMessage task) {
        TaskMessage.TaskConfigMessage config = task.getConfig();
        int timeout = config != null && config.getTimeout() != null ? 
            config.getTimeout() : this.config.getScreenshot().getDefaultTimeout();
            
        page.setDefaultTimeout(timeout);
        
        try {
            // 设置更长的导航超时时间
            Response response = page.navigate(task.getUrl(), new Page.NavigateOptions()
                .setTimeout(timeout)
                // 使用单个 WaitUntilState，等待网络空闲
                .setWaitUntil(WaitUntilState.NETWORKIDLE));

            if (response == null) {
                throw new Web2ImageException("Navigation returned null response");
            }

            if (!response.ok()) {
                log.error("Page returned status: {} {}", response.status(), response.statusText());
                throw new Web2ImageException("Failed to load page: " + task.getUrl() + 
                    " (Status: " + response.status() + ")");
            }

            // 等待页面加载完成
            page.waitForLoadState(LoadState.DOMCONTENTLOADED);
            page.waitForLoadState(LoadState.LOAD);
            
            // 等待网络空闲
            try {
                page.waitForLoadState(LoadState.NETWORKIDLE, 
                    new Page.WaitForLoadStateOptions().setTimeout(timeout));
            } catch (TimeoutError e) {
                log.warn("Network idle timeout for URL: {}", task.getUrl());
                // 继续执行，不抛出异常
            }

            // 额外等待一段时间，确保动态内容加载完成
            page.waitForTimeout(1000);

        } catch (TimeoutError e) {
            throw new Web2ImageException("Page load timeout: " + task.getUrl(), e);
        } catch (PlaywrightException e) {
            throw new Web2ImageException("Failed to load page: " + task.getUrl(), e);
        }
    }

    private Page.ScreenshotOptions createScreenshotOptions(TaskMessage task, Path path) {
        Page.ScreenshotOptions options = new Page.ScreenshotOptions()
                .setPath(path)
                .setFullPage("full".equals(task.getCaptureMode()));

        if ("png".equalsIgnoreCase(task.getFormat())) {
            options.setType(ScreenshotType.PNG);
        } else {
            options.setType(ScreenshotType.JPEG)
                  .setQuality(task.getQuality() != null ? task.getQuality() : 90);
        }

        return options;
    }
} 